package com.lysj.bhp.api.controller;


import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.lysj.bhp.api.dto.EditInfoDto;
import com.lysj.bhp.approve.base.ApproveContent;
import com.lysj.bhp.approve.domain.ApproveRecord;
import com.lysj.bhp.approve.service.PhoneCertificationService;
import com.lysj.bhp.resource.base.ResourceConst;
import com.lysj.bhp.resource.controller.ResourceController;
import com.lysj.bhp.system.domain.Verify;
import com.lysj.bhp.system.domain.VerifyEmail;
import com.lysj.bhp.system.domain.VerifyPhone;
import com.lysj.bhp.system.repository.VerifyEmailRepository;
import com.lysj.bhp.system.repository.VerifyPhoneRepository;
import com.lysj.bhp.system.repository.VerifyRepository;
import com.lysj.bhp.user.base.UserContent;
import com.lysj.bhp.user.domain.User;
import com.lysj.bhp.util.random.RandomUtil;
import com.lysj.bhp.util.sms.MoYunSMSUtil;
import com.lysj.bhp.util.web.ParamUtil;
import com.lysj.bhp.util.web.Resp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RestController
@RequestMapping("api/v2/user")
@Api(value = "UserController", tags = "用户模块接口")
public class ApiUserController extends UserContent {

    @Autowired
    DefaultKaptcha defaultKaptcha;
    @Autowired
    VerifyRepository verifyRepository;
    @Autowired
    VerifyPhoneRepository verifyPhoneRepository;
    @Autowired
    VerifyEmailRepository verifyEmailRepository;

    private final long NEXT_SEND_EMAIL = 1000 * 60 * 3;// 发送邮件间隔(15分钟)
    //    private final long NEXT_SEND_EMAIL = 0;// 发送邮件间隔(用于测试)
    private static final long expires = 1000 * 60 * 3;

    @InitBinder
    public void InitBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, null, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }


    @ApiOperation(value = "修改密码", notes = "")
    @ApiImplicitParam(name = "password", value = "新的密码", required = true, paramType = "query", dataType = "String")
    @PostMapping(value = "/edit_password")
    public Resp editPassword(String oldPassword, String password) {
        if (ParamUtil.isBlack(oldPassword)) {
            return new Resp(Resp.PARAM_ERROR, "请输入旧密码!");
        }
        if (!ParamUtil.md5(oldPassword).equalsIgnoreCase(currentUser().getPassword())) {
            return new Resp(Resp.PARAM_ERROR, "旧密码错误!");
        }
        if (ParamUtil.isBlack(password)) {
            return new Resp(Resp.PARAM_ERROR, "请输入新密码!");
        }
        currentUser().setPassword(ParamUtil.md5(password));
        currentUser().setExpires(System.currentTimeMillis());//使原先的token失效
        userRepository.save(currentUser());
        return new Resp("修改密码成功,请重新登录!");
    }


    /**
     * @author drj
     * @date 2018/8/20 11:06
     * @Description:发送手机验证码
     */
    @ApiOperation(value = "发送手机验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "areacode", value = "区号", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping("/send_verify_code")
    public Resp sendVerifyCode(String phone, String areacode) {
        if (ParamUtil.isBlack(phone)) {
            return new Resp(Resp.PARAM_ERROR, "请填写手机号");
        }
        VerifyPhone verifyQuery = verifyPhoneRepository.findOne(phone);
        // 若存在历史记录且还在拦截器内,则拦截
        if (null != verifyQuery && verifyQuery.getNextSendPhoneMs() > System.currentTimeMillis()) {
            return new Resp(Resp.PARAM_ERROR, "您的操作太频繁,请稍后再进行操作");
        }
        verifyQuery = new VerifyPhone();
        verifyQuery.setPhone(phone);
        verifyQuery.setExpires(System.currentTimeMillis() + verifyRepository.EXPIRE);
        verifyQuery.setNextSendPhoneMs(System.currentTimeMillis() + NEXT_SEND_PHONE);
        verifyQuery.setVerify(RandomUtil.getRandomNum(6));

        boolean result = MoYunSMSUtil.sendVerifySms(verifyQuery.getVerify(), phone, areacode);
        if (!result) {
            return new Resp(Resp.PARAM_ERROR, "短信发送失败,请重试");
        }
        verifyPhoneRepository.save(verifyQuery);
        return new Resp("验证码发送成功");
    }
    /**
     * @author zwj
     * @date 2018-09-18 17:10
     * @@Description:找回密码
     */
    @ApiOperation(value = "手机重置密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "areaCode", value = "区号", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "verify", value = "验证码", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, paramType = "query", dataType = "String"),
    })
    @PostMapping(value = "/phone_reset_password")
    public Resp phoneResetPassword(String areaCode,String phone,String verify,String password){
        if (ParamUtil.isBlack(areaCode)) {
            return new Resp(Resp.PARAM_ERROR, "请选择区号");
        }
        if (ParamUtil.isBlack(phone)) {
            return new Resp(Resp.PARAM_ERROR, "请输入手机号");
        }
        if (ParamUtil.isBlack(password)) {
            return new Resp(Resp.PARAM_ERROR, "请输入重置密码");
        }
        if (ParamUtil.isBlack(verify)) {
            return new Resp(Resp.PARAM_ERROR, "请输入验证码");
        }
        String message = phoneCertificationService.verifyCode(phone, verify);
        if (!ParamUtil.isBlack(message)) {
            return new Resp(Resp.PARAM_ERROR, message);
        }
        User user = userRepository.findByPhoneAndAreaCode(phone,areaCode);
        if(user == null){
            return new Resp(Resp.PARAM_ERROR, "无此用户!");
        }
        if(password.equalsIgnoreCase(user.getPassword())){
            return new Resp(Resp.PARAM_ERROR, "设置失败,新密码不能与旧密码相同!");
        }
        user.setPassword(password);
        userRepository.save(user);
        return new Resp("密码重置成功!");
    }




    @ApiOperation(value = "获取邮箱验证码")
    @ApiImplicitParam(name = "verify", value = "图形验证码", required = true, paramType = "query", dataType = "String")
    @PostMapping(value = "/fetch_my_email_verify_code")
    public Resp fetchMyEmailVerifyCode(String verify) {
        if (ParamUtil.isBlack(verify)) {
            return new Resp(Resp.PARAM_ERROR, "验证码错误");
        }
        Verify verifyQuery = verifyRepository.findOne(currentUser().getEmail());
        if (verifyQuery == null) {
            return new Resp(Resp.PARAM_ERROR, "验证码错误");
        }
        if (!verify.equalsIgnoreCase(verifyQuery.getVerify())) {
            return new Resp(Resp.PARAM_ERROR, "验证码错误");
        }

        VerifyEmail verifyEmailQuery = verifyEmailRepository.findOne(currentUser().getEmail());
        if (System.currentTimeMillis() < verifyEmailQuery.getNextSendEmailMs()) {
            return new Resp(Resp.PARAM_ERROR, "您的操作太频繁,请稍后再进行操作");
        }

        VerifyEmail verifyEmail = new VerifyEmail();
        verifyEmail.setEmail(currentUser().getEmail());
        verifyEmail.setExpires(System.currentTimeMillis() + VerifyEmailRepository.EXPIRE);
        verifyEmail.setVerify(RandomUtil.getRandomString(5));
        verifyEmail.setNextSendEmailMs(System.currentTimeMillis() + NEXT_SEND_EMAIL);// 设置下次发送邮件的时间
        verifyEmailRepository.save(verifyEmail);
        boolean result = mailService.sendVerifyCodeHtmlMail(verifyEmail.getEmail(), verifyEmail.getVerify());
        if (!result) {
            return new Resp(Resp.PARAM_ERROR, "邮件发送失败,请重试");
        }
        return new Resp("获取邮箱验证码成功");
    }
    @ApiOperation(value = "获取邮箱验证码")
    @ApiImplicitParam(name = "email", value = "邮箱", required = true, paramType = "query", dataType = "String")
    @PostMapping(value = "/get_my_email_verify_code")
    public Resp getMyEmailVerifyCode(String email) {
        if (ParamUtil.isBlack(email)) {
            return new Resp(Resp.PARAM_ERROR, "请输入邮箱!");
        }
        User user = userRepository.findByEmail(email);
        if(user != null){
            return new Resp(Resp.PARAM_ERROR, "邮箱已经被绑定!");
        };
        Verify verifyQuery = verifyRepository.findOne(email);
        if (null != verifyQuery && verifyQuery.getNextSendEmailMs() > System.currentTimeMillis()) {
            return new Resp(Resp.PARAM_ERROR, "您的操作太频繁,请稍后再进行操作");
        }
        verifyQuery = new Verify();
        verifyQuery.setEmail(email);
        verifyQuery.setExpires(System.currentTimeMillis() + verifyRepository.EXPIRE);
        verifyQuery.setNextSendEmailMs(System.currentTimeMillis() + NEXT_SEND_EMAIL);
        verifyQuery.setVerify(RandomUtil.getRandomString(5));

        verifyRepository.save(verifyQuery);
        boolean result = mailService.sendVerifyCodeHtmlMail(verifyQuery.getEmail(), verifyQuery.getVerify());
        if (!result) {
            return new Resp(Resp.PARAM_ERROR, "邮件发送失败,请重试");
        }
        return new Resp("获取邮箱验证码成功");
    }

    @ApiOperation(value = "绑定邮箱")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "email", value = "邮箱", required = true, paramType = "query", dataType = "String"),
            @ApiImplicitParam(name = "verify", value = "验证码", required = true, paramType = "query", dataType = "String")
    })
    @PostMapping(value = "/user_binding_email")
    public Resp userBindingEmail(Verify model){
        if(ParamUtil.isBlack(model.getEmail())){
            return new Resp(Resp.PARAM_ERROR,"请输入邮箱");
        }
        if(ParamUtil.isBlack(model.getVerify())){
            return new Resp(Resp.PARAM_ERROR,"请输入邮箱验证码");
        }
        User user = userRepository.findByEmail(model.getEmail());
        if(user != null){
            return new Resp(Resp.PARAM_ERROR, "邮箱已经被绑定!");
        };
        Verify verify = verifyRepository.findOne(model.getEmail());
        if(verify == null){
            return new Resp(Resp.PARAM_ERROR, "验证码错误");
        }
        if(!model.getVerify().equals(verify.getVerify())){
            return new Resp(Resp.PARAM_ERROR, "验证码错误");
        }
        if (System.currentTimeMillis() > verify.getExpires()) {
            return new Resp(Resp.PARAM_ERROR, "验证码已失效，请重新操作");
        }
        user = currentUser();
        user.setEmail(model.getEmail());
        userRepository.save(user);
        //给认证表添加邮箱
        ApproveRecord approveRecord = approveRecordRepository.findByUserId(user.getUserId());
        approveRecord.setEmail(model.getEmail());
        approveRecordRepository.save(approveRecord);
        return new Resp("绑定邮箱成功!");
    }


    @ApiOperation(value = "认证界面显示个人信息", notes = "")
    @PostMapping(value = "/show_certification_info")
    public Resp showCertificationInfo() {
        ApproveRecord approveRecord = approveRecordRepository.findByUserId(currentUser().getUserId());
        return new Resp(approveRecord);
    }

    /**
     * @author zwj
     * @date 2018-08-24 14:38
     * @@Description: 上传身份证正面接口
     */
    @ApiOperation(value = "上传认证照片", notes = "")
    @PostMapping("/upload_approve_photo")
    public Resp uploadIdentyFrontPhoto(MultipartFile[] file) throws Exception {
        if (file.length != 1) {
            return new Resp(Resp.PARAM_ERROR, "图片有误,请重新上传!");
        }
        String filename = System.currentTimeMillis() + "_" + ParamUtil.uuid();
        String path = ResourceConst.BASE_LOCAL_RESOURCE_IMAGES_DIR + "approve";
        String realFileName = ResourceController.fileUpload(file[0], path, filename);
        Map<String, Object> map = new HashMap<>();
        map.put("photo", realFileName);
        return new Resp(map);
    }


    @ApiOperation(value = "手机认证", notes = "3个参数：1.phone 手机号,2.verify 验证码,3.areacode 区号 ")
    @PostMapping(value = "/phone_certification")
    public Resp phoneCertification(String areacode, String phone, String verify) {

        return phoneCertificationService.phoneCertification(areacode, phone, verify);
    }

    @ApiOperation(value = "修改紧急联系人信息", notes = "3个参数：1.urgentContacts 紧急联系人,2.urgentContactsPhone 紧急联系人电话")
    @PostMapping(value = "/edit_contact_info")
    public Resp editInfo(String urgentContacts, String urgentContactsPhone) {
        if (ParamUtil.isBlack(urgentContacts)) {
            return new Resp(Resp.PARAM_ERROR, "请填写紧急联系人");
        }
        if (ParamUtil.isBlack(urgentContactsPhone)) {
            return new Resp(Resp.PARAM_ERROR, "请填写紧急联系人电话");
        }
        ApproveRecord approveRecordQuery = approveRecordRepository.findByUserId(currentUser().getUserId());
        if (null == approveRecordQuery) {
            return new Resp(11, "请先进行手机认证");
        }
        approveRecordQuery.setUrgentContacts(urgentContacts);
        approveRecordQuery.setUrgentContactsPhone(urgentContactsPhone);
        approveRecordQuery.setContactStatus(1); //紧急联系人信息设置成功
        approveRecordRepository.save(approveRecordQuery);
        return new Resp("设置成功");
    }

    @ApiOperation(value = "身份证认证", notes = "6个参数：1.realname 真实姓名,2.birthday 生日,3.address 居住地,4.idNum 身份证号码,5.sex性别 0.女 1.男.6.idCardFrontPhoto 身份证正面信息,7.idCardBackPhoto 身份证反面信息")
    @PostMapping(value = "/id_card_certification")
    public Resp idCardCertification(ApproveRecord model) {
        ApproveRecord approveRecordQuery = approveRecordRepository.findByUserId(currentUser().getUserId());
        if (null == approveRecordQuery) {
            return new Resp(11, "请先进行手机认证");
        }
        //判定紧急联系人是否设置
        if (0 == approveRecordQuery.getContactStatus()) {
            return new Resp(12, "请先完善联系人信息");
        }
        if (2 == approveRecordQuery.getInfoStatus()) {
            return new Resp(Resp.PARAM_ERROR, "您的身份认证信息已审核通过");
        }
        //若已经上传,或者审核成功则无需进行认证
        if (2 == approveRecordQuery.getPptStatus() || 2 == approveRecordQuery.getIdCardStatus()) {
            return new Resp(23, "您的身份认证信息正在审核中,请勿重复提交");
        }
        //判空操作
        if (ParamUtil.isBlack(model.getRealname())) {
            return new Resp(Resp.PARAM_ERROR, "请填写真实姓名");
        }
        if (ParamUtil.isBlack(model.getBirthday())) {
            return new Resp(Resp.PARAM_ERROR, "请填写出生年月");
        }
        if (ParamUtil.isBlack(model.getAddress())) {
            return new Resp(Resp.PARAM_ERROR, "请填写居住地");
        }
        if (ParamUtil.isBlack(model.getIdNum())) {
            return new Resp(Resp.PARAM_ERROR, "请填写身份证号码");
        }
        Integer[] typeIds = new Integer[2];
        typeIds[0] = 1;
        typeIds[1] = 2;
        int idNum = approveRecordRepository.countByIdNumAndIdCardStatusIn(model.getIdNum(),typeIds);
        if (idNum >= 1) {
            return new Resp(Resp.PARAM_ERROR, "该身份证号码已经被使用");
        }
        if (ParamUtil.isBlack(model.getSex())) {
            return new Resp(Resp.PARAM_ERROR, "请填写性别");
        }
        if (ParamUtil.isBlack(model.getIdCardFrontPhoto())) {
            return new Resp(Resp.PARAM_ERROR, "请上传身份证正面照");
        }
        if (ParamUtil.isBlack(model.getIdCardBackPhoto())) {
            return new Resp(Resp.PARAM_ERROR, "请上传身份证反面照");
        }
        approveRecordQuery.setRealname(model.getRealname());
        approveRecordQuery.setAddress(model.getAddress());
        approveRecordQuery.setNation(model.getNation());
        approveRecordQuery.setSex(model.getSex());
        approveRecordQuery.setBirthday(model.getBirthday());
        approveRecordQuery.setIdNum(model.getIdNum());
        approveRecordQuery.setIdCardFrontPhoto(model.getIdCardFrontPhoto());
        approveRecordQuery.setIdCardBackPhoto(model.getIdCardBackPhoto());

        approveRecordQuery.setIdCardStatus(2);//身份证信息待审核状态
        approveRecordQuery.setIdCardRenewalDate(new Date());
        approveRecordRepository.save(approveRecordQuery);
        return new Resp("身份证信息上传成功");
    }

    @ApiOperation(value = "护照认证", notes = "8个参数：1.nationality 国籍, 2.firstName firstName,3.lastName lastName,4.pptNum 护照号,5.pptFrontPhoto 护照正面信息,6.pptBackPhoto 护照反面信息,7.expiryDate 过期日 8 pptBirthday护照生日")
    @PostMapping(value = "/ppt_certification")
    public Resp pptidCardCertification(ApproveRecord model) {
        ApproveRecord approveRecordQuery = approveRecordRepository.findByUserId(currentUser().getUserId());
        if (null == approveRecordQuery) {
            return new Resp(11, "请先进行手机认证");
        }
        //判定紧急联系人是否设置
        if (0 == approveRecordQuery.getContactStatus()) {
            return new Resp(12, "请先完善联系人信息");
        }
        if (2 == approveRecordQuery.getInfoStatus()) {
            return new Resp(Resp.PARAM_ERROR, "您的身份认证信息已审核通过");
        }
        //若已经上传,或者审核成功则无需进行认证
        if (2 == approveRecordQuery.getPptStatus() || 2 == approveRecordQuery.getIdCardStatus()) {
            return new Resp(23, "您的身份认证信息正在审核中,请勿重复提交");
        }
        //判空操作
        if (ParamUtil.isBlack(model.getNationality())) {
            return new Resp(Resp.PARAM_ERROR, "请填写国籍");
        }
        if (ParamUtil.isBlack(model.getPptBirthday())) {
            return new Resp(Resp.PARAM_ERROR, "请填写护照生日号");
        }
        if (ParamUtil.isBlack(model.getFirstName())) {
            return new Resp(Resp.PARAM_ERROR, "请填写firstName");
        }
        if (ParamUtil.isBlack(model.getLastName())) {
            return new Resp(Resp.PARAM_ERROR, "请填写lastName");
        }
        if (ParamUtil.isBlack(model.getPptNum())) {
            return new Resp(Resp.PARAM_ERROR, "请填写护照号码");
        }
        Integer[] typeIds = new Integer[2];
        typeIds[0] = 1;
        typeIds[1] = 2;
        int pptNum = approveRecordRepository.countByPptNumAndPptStatusIn(model.getPptNum(),typeIds);
        if (pptNum >= 1) {
            return new Resp(Resp.PARAM_ERROR, "该护照号码已经被使用");
        }
        if (ParamUtil.isBlack(model.getPptFrontPhoto())) {
            return new Resp(Resp.PARAM_ERROR, "请上传护照正面照");
        }
        if (ParamUtil.isBlack(model.getPptBackPhoto())) {
            return new Resp(Resp.PARAM_ERROR, "请上传护照反面照");
        }
        if (ParamUtil.isBlack(model.getExpiryDate())) {
            return new Resp(Resp.PARAM_ERROR, "请填写过期日");
        }
        approveRecordQuery.setPptBirthday(model.getPptBirthday());
        approveRecordQuery.setNationality(model.getNationality());
        approveRecordQuery.setFirstName(model.getFirstName());
        approveRecordQuery.setLastName(model.getLastName());
        approveRecordQuery.setPptNum(model.getPptNum());
        approveRecordQuery.setExpiryDate(model.getExpiryDate());
        approveRecordQuery.setPptFrontPhoto(model.getPptFrontPhoto());
        approveRecordQuery.setPptBackPhoto(model.getPptBackPhoto());

        approveRecordQuery.setPptStatus(2);//护照信息待审核状态
        approveRecordQuery.setPptRenewalDate(new Date());
        approveRecordRepository.save(approveRecordQuery);
        return new Resp("护照信息上传成功");
    }

    @ApiOperation(value = "手持认证", notes = "参数：multiplePhoto 手持照片")
    @PostMapping(value = "/mlp_certification")
    public Resp pptidCardCertification(String multiplePhoto) {
        //判空操作
        if (ParamUtil.isBlack(multiplePhoto)) {
            return new Resp(Resp.PARAM_ERROR, "手持照片不能为空");
        }
        ApproveRecord approveRecordQuery = approveRecordRepository.findByUserId(currentUser().getUserId());
        if (null == approveRecordQuery) {
            return new Resp(11, "请先进行手机认证");
        }
        //判定紧急联系人是否设置
        if (0 == approveRecordQuery.getContactStatus()) {
            return new Resp(12, "请先完善联系人信息");
        }
        if (3 == approveRecordQuery.getInfoStatus()) {
            return new Resp(Resp.PARAM_ERROR, "您的三级认证已通过,请勿重复操作");
        }
        if (2 != approveRecordQuery.getInfoStatus()) {
            if (2 == approveRecordQuery.getPptStatus() || 2 == approveRecordQuery.getIdCardStatus()) {
                return new Resp(23, "您的身份认证信息正在审核中,请耐心等待");
            } else {
                return new Resp(22, "请先进行身份认证");
            }
        }
        approveRecordQuery.setMultiplePhoto(multiplePhoto);
        approveRecordQuery.setMultipleStatus(2);//手持照信息待审核状态
        approveRecordQuery.setMultipleRenewalDate(new Date());
        approveRecordRepository.save(approveRecordQuery);
        return new Resp("手持照信息上传成功");
    }


}
